#include "main.h"
#include "pump.h"
#include "string.h"
#include "bsp_uart_fifo.h"
#include "modbus.h"
#include "event.h"


/*
  command format:
    start  addr   sn     data(n)  end   checksum
    0x02   0x3x   0x31   n*0xXX   0x03  0xXX

  all cmds:
    Z: initial to right(right out)
    Y: initial to left (left out)
    I: to input position
    O: to output position
    B: to bypass position

    A(0-6000): absolute position
    P(0-6000): move down
    D(0-6000): move up

    R: execute the command immediately
    X: repeat last command
    g..G(n):repeat command 0:endless 1-30000  e.g.: gIA6000OA0G5
    M(n): delay ms then execute 5-30000ms     e.g.: M1000A500
    H: halt command
    T: terminate command
    s(0-14): save command to e2prom
    e(0-14): execute command from e2prom

    K(0-31): back compensate displacement default:0
    L(1-20): speed slope default:7 
    v(50-1000):pump start speed default:900
    V(5-5000):pump run speed  default:1400
    c(50-2700): pump stop speed default:900
    S(1-40): valve speed default default:11
    
*/

static char g_cmd[CMD_SIZE] = {0};

char checksum(char *data, char len)
{
    char i;
    char ret=0;
    
    for(i = 0; i < len; i++){
       ret ^= data[i];
    }

    return ret;
}

void get_pump_cmd(char * cmd, int pump_addr)
{  
    int i=3;

    if(*cmd == 0)
        return;
    
    memset(g_cmd,0,sizeof(g_cmd));
    g_cmd[0] = START;
    g_cmd[1] = ADDR_BASE + pump_addr;
    g_cmd[2] = SN;

    sprintf(&g_cmd[i],"%s",cmd);
    i += strlen(&g_cmd[i]); 
    g_cmd[i] = 'R';
    i++;
    g_cmd[i] = END;
    i++;
    g_cmd[i] = checksum(g_cmd,i);
}

void pump_cmd_ex(int para)
{  
    int i=4;
    sprintf(&g_cmd[i], "%d", para);
    i += strlen(&g_cmd[i]); 
    g_cmd[i] = 'R';
    i++;
    g_cmd[i] = END;
    i++;
    g_cmd[i] = checksum(g_cmd,i);
}

void pump_cmd(PumpCmdType cmd, int addr, int para)
{  
    int i=3;
    
    memset(g_cmd,0,sizeof(g_cmd));
    g_cmd[0] = START;
    g_cmd[1] = ADDR_BASE + addr;
    g_cmd[2] = SN;

    switch(cmd){
    case kPumpInitOutToLeft:
        get_pump_cmd("Y", addr);     //init input to left
    break;
    case kPumpInitOutToRight:        //init input to right
        get_pump_cmd("Z", addr);

    break;
    case kPumpInput:
        get_pump_cmd("I", addr);

    break;
    case kPumpOutput :
        get_pump_cmd("O", addr);

    break;
    case kPumpStop :
        get_pump_cmd("T", addr);

    break;
    case kPumpUp:
        g_cmd[i] = 'D';
        i++;
        pump_cmd_ex(para);
    break;
    case kPumpDown:
        g_cmd[i] = 'P';
        i++;
        pump_cmd_ex(para);
    break;
    case kPumpMoveTo:
        g_cmd[i] = 'A';
        i++;
        pump_cmd_ex(para);
        break;
    case kPumpSetSpeed:
        g_cmd[i] = 'V';
        i++;
        pump_cmd_ex(para);
        break;
    case kPumpUser:
        break;
    default:
        break;
    }  
}

void execute_pump_cmd(PumpCmdType cmd, int para, int pump_addr)
{
    pump_cmd(cmd, pump_addr, para);
    if (pump_addr == ADDR1)
        Uart1SendData(g_cmd, strlen(g_cmd));
    else if(pump_addr == ADDR2)
        Uart4SendData(g_cmd, strlen(g_cmd));
}

void execute_pump_cmd_str(char *cmd_string, int pump_addr)
{
    get_pump_cmd(cmd_string, pump_addr);

    if (pump_addr == ADDR1)
        Uart1SendData(g_cmd, strlen(g_cmd));
    else if(pump_addr == ADDR2)
        Uart4SendData(g_cmd, strlen(g_cmd));
}

void foo_bar(void)
{
    printf("time:%dms,halt!!!", ssz_tick_time_now());
    halt;
}

//gIV3000A6000V600OA0G0
void execute_pump_auto(int fill_speed,int dose_speed,int volume, int pump_addr)
{
    int i=3;
 
    memset(g_cmd,0,sizeof(g_cmd));
    g_cmd[0] = START;
    g_cmd[1] = ADDR_BASE + pump_addr;
    g_cmd[2] = SN;

    g_cmd[i] = 'g';
    i++;

    g_cmd[i] = 'I';
    i++;

    g_cmd[i] = 'V';
    i++;
    sprintf(&g_cmd[i],"%d",fill_speed);
    i += strlen(&g_cmd[i]); 
 
    g_cmd[i] = 'A';
    i++;
    sprintf(&g_cmd[i],"%d",volume);
    i += strlen(&g_cmd[i]);

    g_cmd[i]='V';
    i++;
    sprintf(&g_cmd[i],"%d",dose_speed);
    i += strlen(&g_cmd[i]);

    g_cmd[i] = 'O';
    i++;
    g_cmd[i] = 'A';
    i++;
    g_cmd[i] = '0';
    i++;
    g_cmd[i] = 'G';
    i++;
    g_cmd[i] = '0';
    i++;

    g_cmd[i] = 'R';
    i++;
    g_cmd[i] = END;
    i++;
    g_cmd[i] = checksum(g_cmd,i);
    
    if (pump_addr == ADDR1)
        Uart1SendData(g_cmd, strlen(g_cmd));
    else if(pump_addr == ADDR2)
        Uart4SendData(g_cmd, strlen(g_cmd));


}

PumpModeType pump_mode_get(vu16 mode)
{
    PumpModeType ret=kPumpModeMax;

    switch (mode) {
        case 1:
            ret = kPumpFill;
            break;
        case 2:
            ret = kPumpPrep;
            break;
        case 3:
            ret = kPumpDose;
            break;
        case 4:
            ret = kPumpEmpty;
            break;
        case 5:
            ret = kPumpClean;
            break;
        case 6:
            ret = kPumpFeed;
            break;
        default:
            break;
    }

    return ret;
}


void pump_power_on_init1(void)
{
    execute_pump_cmd_str("ZIV2000A6000", ADDR1);
}

void pump_power_on_init2(void)
{
    execute_pump_cmd_str("ZIV2000A6000", ADDR2);
}

void pump_init_left1(void)
{
    execute_pump_cmd(kPumpInitOutToLeft, 0, ADDR1);
}
void pump_init_left2(void)
{
    execute_pump_cmd(kPumpInitOutToLeft, 0, ADDR2);
}

void pump_init_right1(void)
{
    execute_pump_cmd(kPumpInitOutToRight, 0, ADDR1);
}
void pump_init_right2(void)
{
    execute_pump_cmd(kPumpInitOutToRight, 0, ADDR2);
}

int pump_speed(int speed)
{
    int ret = (int)((speed / 1000.0) * 10);

    if (ret < 0) return 1400;

    if(ret < 5){
        ret = 5;
    } else if (ret > 5000){
        ret = 5000;
    }

    return ret;
}

//auto mode start here
void pump_start(struct pump_maunual_para struct_data, int pump_addr)
{
    char tmp[30] = {0};
    int volume = 0;

    volume = (int)((struct_data.volume / 1000.0) * 600);
    if (volume < 0)
        volume = 0;
    else if (volume > 6000)
        volume = 6000;

    if (struct_data.clean_times > 30000)   struct_data.clean_times = 30000;
    if (struct_data.feed_times > 30000)    struct_data.feed_times = 30000;


    if (pump_mode_get(struct_data.mode) == kPumpPrep) {
        sprintf(tmp,"OV1400A0IA%d", volume);
        execute_pump_cmd_str(tmp, pump_addr);
    } else if (pump_mode_get(struct_data.mode) == kPumpEmpty) {
        execute_pump_cmd_str("OV2000A0", pump_addr);
    } else if (pump_mode_get(struct_data.mode) == kPumpClean) {     
        sprintf(tmp,"gV%dIA%dOV%dA0G%d", pump_speed(struct_data.fill_speed), volume,
            pump_speed(struct_data.dose_speed), struct_data.clean_times); //gV3000IA6000OA0G2
        execute_pump_cmd_str(tmp, pump_addr);
    } else if (pump_mode_get(struct_data.mode) == kPumpFeed) {
        sprintf(tmp,"gV%dIA%dOV%dA0G%d", pump_speed(struct_data.fill_speed), volume,
            pump_speed(struct_data.dose_speed), struct_data.feed_times);   //gV3000IA6000OA0G2
        execute_pump_cmd_str(tmp, pump_addr);
    }
}

void pump_start1(void)
{
    pump_start(g_pump_manual_para[kPumpOne], ADDR1);
}
void pump_start2(void)
{
    pump_start(g_pump_manual_para[kPumpTwo], ADDR2);
}

//manual mode start here
void pump_manual_start(struct pump_maunual_para struct_data, int pump_addr)
{
    char tmp[20] = {0};
    
    if (pump_mode_get(struct_data.mode) == kPumpFill) {
        sprintf(tmp, "IV%dP%d", pump_speed(struct_data.fill_speed), (int)((struct_data.manual_filling / 1000.0) * 600));
        execute_pump_cmd_str(tmp, pump_addr);
    } else if (pump_mode_get(struct_data.mode) == kPumpDose) {
        sprintf(tmp, "OV%dD%d", pump_speed(struct_data.dose_speed), (int)((struct_data.manual_dosing / 1000.0) * 600));
        execute_pump_cmd_str(tmp, pump_addr);
    }
}
void pump_manual_start1(void)
{
    pump_manual_start(g_pump_manual_para[kPumpOne], ADDR1);
}
void pump_manual_start2(void)
{
    pump_manual_start(g_pump_manual_para[kPumpTwo], ADDR2);
}


//auto mode start here
void pump_auto_start(struct pump_auto_para struct_data, int pump_addr)
{
    char tmp[20] = {0};
    sprintf(tmp, "OV%dD%d", pump_speed(struct_data.auto_speed), (int)((struct_data.auto_volume / 1000.0) * 600));
    execute_pump_cmd_str(tmp, pump_addr);
}
void pump_auto_start_1(void)
{
    pump_auto_start(g_pump_auto_para[kPumpOne], ADDR1);
}
void pump_auto_start_2(void)
{
    pump_auto_start(g_pump_auto_para[kPumpTwo], ADDR2);
}


void pump_stop(int pump_addr)
{
    execute_pump_cmd(kPumpStop, 0, pump_addr);
}

void pump_stop1(void)
{
    execute_pump_cmd(kPumpStop, 0, ADDR1);
}
void pump_stop2(void)
{
    execute_pump_cmd(kPumpStop, 0, ADDR2);
}


void pump_event_handler_init(void)
{
    event_set_handler(kEventStartPump1, pump_start1);
    event_set_handler(kEventStopPump1, pump_stop1);
    event_set_handler(kEventManualFillDose1, pump_manual_start1);
    event_set_handler(kEventAutoStartPump1, pump_auto_start_1);

    event_set_handler(kEventStartPump2, pump_start2);
    event_set_handler(kEventStopPump2, pump_stop2);
    event_set_handler(kEventManualFillDose2, pump_manual_start2);
    event_set_handler(kEventAutoStartPump2, pump_auto_start_2);
}



